from django.shortcuts import render

# Create your views here.
#购物车
#未登录保存在浏览器，登录的保存在数据库服务器redis
#cookie >>sku_id,count,selected(是否勾取选择)
#redis >>>userid,sku_id,count,selected(是否勾取选择)
#hash set 可以达到优化程序，节约缓存服务器空间  程序换空间

from django.views import View
import json
from apps.goods.models import SKU
from django.http import HttpResponseBadRequest,JsonResponse
from django_redis import get_redis_connection
import base64
import pickle

"""
    增加购物车的逻辑

    请求
        参数： sku_id  count

    业务逻辑
        1. 接收请求数据
        2. 验证数据
            2.1 验证商品id是否存储
            2.2 数量是否整形
        3. 获取用户信息。根据用户信息来判断
        4.如果是登录用户保存在redis
            4.1 连接redis
            4.2 操作hash
            4.3 操作set
            4.4 返回响应
        5.如果是未登录用户保存在cookie
            5.1 初始化一个空字典
            5.2 将数据添加到字典中
            5.3 字典转换为bytes类型
            5.4 base64加密
            5.5 设置cookie
            5.6 返回响应
    响应
"""


class CartView(View):
    def post(self,request):
        #接收请求
        data = json.loads(request.body.decode())
        sku_id=data.get('sku_id')
        count=data.get('count')
        #验证，id是否保存
        try:
            sku=SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return JsonResponse({'code':400,'errmsg':'无此商品'})
        #数量是否int
        try:
            count=int(count)
        except Exception:
            count=1
        #3.获取用户信息根据用户信息判断
        #系统通过中间件添加的属性request.user
        user=request.user
        #区分登录用户是匿名还是认证
        if user.is_authenticated:
            redis_cli=get_redis_connection('cart')

        #hash  increaseby
            redis_cli.hincrby('cart_s'%user.id,sku_id,count)
            #set
            redis_cli.sadd('selected_%s'%user.id,sku_id)
            return JsonResponse({'code': 0, 'errmsg': 'ok'})

        else:
            #未登录用户保存于cookie
            #读取cookie判断是否有数据
            cookie_carts=request.COOKIE.get('carts')
            if cookie_carts is None:
                #没有则初始化
                carts={}
            else:
                #有则数据解码
                carts=pickle.loads(base64.b64decode(cookie_carts))
            #再更新数据
            if sku_id in carts:
                #原有+现在的
                origin_count=carts[sku_id]['count']
                count+=origin_count

            #添加数据到字典
            carts[sku_id]={
                'count': count,
                'selected': True

            }
            #字典转换bytes
            carts_bytes=pickle.dumps(carts)
            #base64加密
            carts_base64=base64.b64encode(carts_bytes)
            #设置cookie
            response=JsonResponse({'code':0,'errmsg':'ok'})
            response.set_cookie(key='carts',value=carts_base64.decode(),max_age=24*3600)

            return response

    """
    1.接收请求中的user信息
    2.如果是登录用户则获取redis的数据
        2.1 连接redis
        2.2 获取set数据     [1,2,3]
        2.3 获取hash数据    {1:10,2:10,3:10}
        2.4 获取商品的id。根据商品的id查询商品详细信息
        2.5 将对象数据转换为字典数据
        2.6 返回响应
    3.如果不是登录用户则获取cookie的数据
        3.1 读取cookie数据，获取购物车数据
        3.2 判断购物车是否有数据
        3.3 如果有数据则进行解密  {1：{count:10,selected:True},2:{count:10,selected:False}}
        3.4 如果没有数据则初始化一个空列表
        3.5 获取商品的id。根据商品id查询商品的详细信息
        3.6.将对象数据转换为字典数据
        3.7 返回响应


    """

    def get(self, request):
        # 1.接收请求中的user信息
        user = request.user
        if user.is_authenticated:
            # 2.如果是登录用户则获取redis的数据
            #      连接redis
            redis_cli = get_redis_connection('carts')
            #    获取set数据
            selected_ids = redis_cli.smembers('selected_%s' % user.id)
            #     获取hash数据
            sku_id_counts = redis_cli.hgetall('carts_%s' % user.id)
            # 把redis的数据转换为和cookie一样的格式
            # {1：{count:10,selected:True},2:{count:10,selected:False}}
            carts = {}

            # {1:10,2:10:3:10}
            for sku_id, count in sku_id_counts.items():
                carts[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in selected_ids
                }

            # in 判断 sku_id 是否集合中

        else:
            # 3.如果不是登录用户则获取cookie的数据
            #     3.1 读取cookie数据，获取购物车数据
            cookie_carts = request.COOKIES.get('carts')
            #     3.2 判断购物车是否有数据
            if cookie_carts is not None:
                #     3.3 如果有数据则进行解密  {1：{count:10,selected:True},2:{count:10,selected:False}}
                carts = pickle.loads(base64.b64decode(cookie_carts))
            else:
                #     3.4 如果没有数据则初始化一个空列表
                carts = {}

        # 4 获取商品的id。根据商品id查询商品的详细信息
        # {1：{count:10,selected:True},2:{count:10,selected:False}}
        # 获取字典的所有的sku_id (key)
        ids = carts.keys()
        # ids = [1,2,3,4]
        skus = SKU.objects.filter(id__in=ids)
        # 5.将对象数据转换为字典数据
        sku_list = []
        for sku in skus:
            sku_list.append({
                'id': sku.id,
                'name': sku.name,
                'count': carts.get(sku.id).get('count'),
                'selected': carts.get(sku.id).get('selected'),
                'default_image_url': sku.default_image.url,
                'price': str(sku.price),  # 从Decimal('10.2')中取出'10.2'，方便json解析
                'amount': str(sku.price * carts.get(sku.id).get('count')),
            })
        # 6.返回响应
        return JsonResponse({'code': 0, 'cart_skus': sku_list, 'errmsg': 'ok'})

    """
    1.接收数据
    2.验证数据（省略）
    3.获取用户信息
    4.登录用户更新redis
        4.1 连接redis
        4.2 更新hash
        4.3 更新set
        4.4 返回响应
    5.未登录用户更新cookie
        5.1 读取cookie中的购物车数据
        5.2 判断购物车数据
        5.3 如果有则解密
        5.4 如果没有则初始化一个空字典
        5.5 判断更新
        5.6 新的字典数据进行加密处理
        5.7 返回响应
    """

    def put(self,request):
        data=json.loads(request.body.decode())

        sku_id=data.get('sku_id')
        count = data.get('count')
        selected = data.get('selected')
        sku = SKU.objects.get(id=sku_id)
        try:
            count=int(count)
        except Exception:
            count=1

        user = request.user
        if user.is_authenticated:
            redis_cli = get_redis_connection('carts')
            #     4.2 更新hash
            redis_cli.hset('carts_%s' % user.id, sku_id, count)
            #     4.3 更新set
            if selected:
                redis_cli.sadd('selected_%s'%user.id,sku_id)
            else:
                redis_cli.srem('selected_%s'%user.id,sku_id)
            #     4.4 返回响应

            cart_sku = {
                'id': sku_id,
                'count': count,
                'selected': selected,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price,
                'amount': sku.price * count,
            }
            return JsonResponse({'code': 0, 'cart_sku': cart_sku})

        else:
    # 5.未登录用户更新cookie
            cookie_cart = request.COOKIES.get('carts')
    #     5.1 读取cookie中的购物车数据
            if cookie_cart is not None:

                carts = pickle.loads(base64.b64decode(cookie_cart))
            else:
        #     5.4 如果没有则初始化一个空字典
                carts = {}
            if sku_id in carts:
                carts[sku_id] = {
                    'count': count,
                    'selected': selected }

            base64_carts = base64.b64encode(pickle.dumps(carts))
            #     5.7 返回响应
            response = JsonResponse({'code': 0, 'count': count})

            response.set_cookie('carts', base64_carts.decode(), max_age=14 * 24 * 3600)

            return response


    def delete(self,request):
        data=json.loads(request.body.decode())
        sku_id=data.get('sku_id')
        user=request.user
        if user.is_authenticated:
            redis_cli=get_redis_connection('carts')
            redis_cli.hdel('carts_%s'%user.id,sku_id)
            redis_cli.srem('selected_%s' % user.id, sku_id)
            return JsonResponse({'code': 0, 'errmsg': 'ok'})
        else:

            cookie_cart = request.COOKIES.get('carts')
            if cookie_cart is not None:
                carts = pickle.loads(base64.b64decode(cookie_cart))
            else:
                carts = {}
            if sku_id in carts:
                del carts[sku_id]

            base64_carts = base64.b64encode(pickle.dumps(carts))
            response = JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('carts', base64_carts.decode(), max_age= 24 * 3600)

            return response












